﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Text.RegularExpressions;
using ICSharpCode.SharpZipLib.BZip2;
using CygwinPackageManager.Common.Properties;
using Microsoft.Win32;
using System.Net;
using System.Runtime.CompilerServices;

namespace CygwinPackageManager.Common
{
	public class AvailablePackageDALC : PackageBaseDALC
	{
		private IEnumerable<AvailablePackage> _availablePackages;
		private IEnumerable<AvailablePackage> AvailablePackages
		{
			get
			{
				if (_availablePackages == null)
					_availablePackages = _GetAvailablePackages();

				return _availablePackages;
			}
			set { _availablePackages = value; }
		}

		private IEnumerable<AvailablePackage> _GetAvailablePackages()
		{
			InstallationInfo installation = InstallationManager.GetInstallationInfo();

			if (!installation.IsReady)
				throw new InvalidOperationException("Cygwin is not ready.");

			// Intepret setup.ini.
			string cacheDirectory = installation.CacheDirectory;
			Uri mirrorUri = installation.LastMirrorUri;

			
			string setupContent = string.Empty;
			try
			{
				setupContent = File.ReadAllText(Utils.GetSetupIniPath(cacheDirectory, mirrorUri.OriginalString));
			}
			catch (Exception ex)
			{
				throw new Exception("Cannot load setup.ini", ex);
			}

			// Build package list.
			List<AvailablePackage> packages = new List<AvailablePackage>();
			foreach (Match packageMatch in Regex.Matches(setupContent, Resources.AvailablePackagesRegex, RegexOptions.Singleline))
			{
				string packageName = packageMatch.Groups["Name"].Value.ExtendedTrim();
				packages.Add(new AvailablePackage
				{
					Text = packageMatch.Value,

					// Extended base information.
					PackageID = GetPackageID(packageName),

					// Base information.
					IsSpecial = packageName.StartsWith("_"),
					Name = packageName,
					ReleaseVersion = packageMatch.Groups["Release"].Value.ExtendedTrim(),
					VendorVersion = packageMatch.Groups["Version"].Value.ExtendedTrim(),

					// Rest.
					Description = packageMatch.Groups["Description"].Value.ExtendedTrim().ToSingleLine(),
					Details = packageMatch.Groups["Details"].Value.ExtendedTrim().ToSingleLine(),
					Requires = new List<string>(packageMatch.Groups["Requires"].Value.ExtendedTrim().Split()),
					Categories = new List<string>(packageMatch.Groups["Categories"].Value.ExtendedTrim().Split()),
				});
			}

			return packages;
		}

		public IEnumerable<AvailablePackage> GetAvailablePackages()
		{
			return AvailablePackages;
		}
	}
}
